#ifndef _DATAGRAM_FACTORY_20120414
#define _DATAGRAM_FACTORY_20120414

#include "base.hpp"
#include "idatagram.hpp"
#include "idatagram_factory.hpp"

namespace datagram
{
	class DatagramFactory : public IDatagramFactory
	{
		public :
			DatagramFactory()
			{
				new (_buffer) IDatagram(-1);
			}

			~DatagramFactory()
			{
				reinterpret_cast<IDatagram*>(_buffer)->~IDatagram();
			}

			virtual int decode(uint32_t type, Streamer & streamer, IDatagram *& datagram);
			virtual void encode(uint32_t type, Streamer & streamer, IDatagram * datagram);
		public :
			char _buffer[IDatagramFactory::MAX_DATAGRAM_SIZE];
	};

	int DatagramFactory::decode(uint32_t type, Streamer & streamer, IDatagram *& datagram)
	{
        int ret = 0;
		switch(type)
		{
#define DATAGRAM_DEF_TYPE(class, name, value) \
			case Datagram::name: \
			{ \
				reinterpret_cast<IDatagram*>(_buffer)->~IDatagram(); \
				datagram  = new (_buffer) class(); \
				streamer & (*datagram); \
                ret = 0; \
                break; \
			}

#include "datagram_def_type.i"

			default :
				{
				    ret = -1;
                    break;
				}
		}
#undef DATAGRAM_DEF_TYPE

		return ret;
	}

	void DatagramFactory::encode(uint32_t type, Streamer & streamer, IDatagram * datagram)
	{
		switch(type)
		{
#define DATAGRAM_DEF_TYPE(class, name, value) \
			case Datagram::name: \
			{ \
				streamer & (*(class*)datagram); \
				break; \
			}

#include "datagram_def_type.i"
			default :
				{
					// @TODO ERROR LOG
					break;
				}

		}
	}
};

#endif

